package br.com.localfloripa.controllers;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.inject.Named;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;

import br.com.localfloripa.dao.ClienteDao;
import br.com.localfloripa.dao.EstadoDao;
import br.com.localfloripa.dao.MunicipioDao;
import br.com.localfloripa.dao.RepresentanteDao;
import br.com.localfloripa.entities.Cliente;
import br.com.localfloripa.entities.Estado;
import br.com.localfloripa.entities.Fotografia;
import br.com.localfloripa.entities.Municipio;
import br.com.localfloripa.entities.PessoaFisica;
import br.com.localfloripa.entities.PessoaJuridica;
import br.com.localfloripa.entities.Plano;
import br.com.localfloripa.entities.Representante;
import br.com.localfloripa.entities.Template;
import br.com.localfloripa.entities.TipoCliente;
import br.com.localfloripa.entities.TipoPessoa;
import br.com.localfloripa.util.FileUtils;
import br.com.localfloripa.util.StringUtils;

@Named("clienteController")
@Scope("session")
public class ClienteController implements Serializable {

	private static final long serialVersionUID = -6953928628623162909L;
	private static final Logger log = LoggerFactory.getLogger(ClienteController.class);
	private static final String UF_DEFAULT = "SC";
	private final Integer pageSize = 10;
	
	@Inject
	@Named("clienteDao")
	private ClienteDao clienteDao; 
	
	@Inject
	@Named("representanteDao")
	private RepresentanteDao representanteDao;
	@Inject
	@Named("municipioDao")
	private MunicipioDao municipioDao;
	@Inject
	@Named("estadoDao")
	private EstadoDao estadoDao;
	
	
	/** form - atributos **/
	private Estado estado;
	private List<Municipio> municipios;
	private List<Estado> estados;
	private List<Cliente> proprietarios;
	
	private LazyDataModel<Cliente> lazyModelCliente;
	private Cliente cliente;
	private Cliente proprietario;
	private String tipoPessoa;
	private String tipoCliente;
	private PessoaFisica pessoaFisica;
	private PessoaJuridica pessoaJuridica;
	private HashMap<String, Fotografia> medias;
	
	/** controla linha selecionada do dataTable **/
	private boolean selectedCliente = false;
	
	public ClienteController() {
		
	}
	
	@PostConstruct
	public void loadModels() {
		lazyModelCliente = new LazyDataModel<Cliente>()  { 

			@Override
			public int getPageSize() {
				return pageSize;
			}

			@Override
			public int getRowCount() {
				return clienteDao.countListClientes().intValue();
			}

			@Override
			public List<Cliente> load(int first, int pageSize, String sortField, SortOrder order, Map<String, String> filters) {
				List<Cliente> clientes = null;
				try {
					clientes = clienteDao.listClientesPaginada(first, pageSize);
				} catch (Exception e) {
					log.error(e.getMessage(),e);
				}				
				return clientes;
			}	
			
			@Override  
		    public Object getRowKey(Cliente cliente) {  
		        return cliente.getId();  
		    } 
			
			@Override  
		    public Cliente getRowData(String rowKey) {  
				
				if (rowKey != null && !rowKey.equals("null")) {
					List<Cliente> clientes = (List<Cliente>) getWrappedData();  
			          
			        for(Cliente cliente : clientes) {  
			            if(cliente.getId().equals(Long.valueOf(rowKey)))  
			                return cliente;  
			        }
				}  		          
		        return null;  
		    }  
			
		};
	}
	
	public String save() {
		ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
		try {			
			
			if (tipoPessoa.equals(TipoPessoa.FISICA.value()))
				cliente.setPessoa(pessoaFisica);
			else
				cliente.setPessoa(pessoaJuridica);
			persistMediaFiles();
			if (tipoCliente.equals(TipoCliente.R.name())) { // cliente representante
				Representante representante = new Representante();
				representante = Representante.parseCliente(cliente);
				representante.setProprietario(clienteDao.findById(proprietario.getId()));
				representante.getEndereco().setMunicipio(municipioDao.findById(representante.getEndereco().getMunicipio().getId()));								
				if (medias.containsKey("logo")) {
					representante.getTemplate().setLogo(medias.get("logo").getNome());
				} else {
					representante.getTemplate().setLogo(null);
				}
				if (medias.containsKey("corretor")) {
					representante.getTemplate().setCorretor(medias.get("corretor").getNome());
				} else {
					representante.getTemplate().setCorretor(null);
				}					
				if (medias.containsKey("banner")) {
					representante.getTemplate().setBanner(medias.get("banner").getNome());
				} else {
					representante.getTemplate().setBanner(null);
				}				
				representanteDao.persist(representante);
			} else if (tipoCliente.equals(TipoCliente.P.name())) { // cliente proprietario
				cliente.getEndereco().setMunicipio(municipioDao.findById(cliente.getEndereco().getMunicipio().getId())); 	
				if (medias.containsKey("logo")) {
					cliente.getTemplate().setLogo(medias.get("logo").getNome());
				} else {
					cliente.getTemplate().setLogo(null);
				}
					
				if (medias.containsKey("banner")) {
					cliente.getTemplate().setBanner(medias.get("banner").getNome());
				} else {
					cliente.getTemplate().setBanner(null);
				}		
				clienteDao.persist(this.cliente);
			}			
			loadModels();
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.info.confirm"), bundle.getString("manager.cliente.create.confirm")));  
			return "/faces/manager/xhtml/cliente/list.xhtml";
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.create.error"))); 
			return "/faces/manager/xhtml/cliente/create.xhtml";
		}
	}
	
	public String update() {
		ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
		try {
			if (tipoPessoa.equals(TipoPessoa.FISICA.value()))
				cliente.setPessoa(pessoaFisica);
			else
				cliente.setPessoa(pessoaJuridica);
			
			persistMediaFiles();
			if (tipoCliente.equals(TipoCliente.R.name())) {
				Representante representante = new Representante();
				representante = Representante.parseCliente(cliente);
				representante.setId(cliente.getId());
				representante.setProprietario(clienteDao.findById(proprietario.getId()));				
				representante.getEndereco().setMunicipio(municipioDao.findById(representante.getEndereco().getMunicipio().getId()));				
				if (medias.containsKey("logo")) {
					representante.getTemplate().setLogo(medias.get("logo").getNome());
				} else {
					representante.getTemplate().setLogo(null);
				}
				if (medias.containsKey("corretor")) {
					representante.getTemplate().setCorretor(medias.get("corretor").getNome());
				} else {
					representante.getTemplate().setCorretor(null);
				}					
				if (medias.containsKey("banner")) {
					representante.getTemplate().setBanner(medias.get("banner").getNome());
				} else {
					representante.getTemplate().setBanner(null);
				}			
				representanteDao.merge(representante);								
			} else if (tipoCliente.equals(TipoCliente.P.name())) {
				cliente.getEndereco().setMunicipio(municipioDao.findById(cliente.getEndereco().getMunicipio().getId())); 
				if (medias.containsKey("logo")) {
					cliente.getTemplate().setLogo(medias.get("logo").getNome());
				} else {
					cliente.getTemplate().setLogo(null);
				}
					
				if (medias.containsKey("banner")) {
					cliente.getTemplate().setBanner(medias.get("banner").getNome());
				} else {
					cliente.getTemplate().setBanner(null);
				}					
				clienteDao.merge(this.cliente);
			}						
			loadModels();
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.info.confirm"), bundle.getString("manager.cliente.update.confirm")));  
			return "/faces/manager/xhtml/cliente/list.xhtml";
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.update.error"))); 
			return "/faces/manager/xhtml/cliente/update.xhtml";
		}
	}
	
	public String edit() {
		if (this.getCliente().getId() != null) {
			if (this.cliente.getPessoa() instanceof PessoaFisica) {
				pessoaFisica = (PessoaFisica) this.cliente.getPessoa();
				this.setTipoPessoa(TipoPessoa.FISICA.value());
			} else if ( this.cliente.getPessoa() instanceof PessoaJuridica ) {
				pessoaJuridica = (PessoaJuridica) this.cliente.getPessoa();
				this.setTipoPessoa(TipoPessoa.JURIDICA.value());
			}	
			try {
				Representante representante = representanteDao.findById(this.cliente.getId());
				if (representante != null) {
					tipoCliente = TipoCliente.R.name();
					proprietario = representante.getProprietario();
				} else {
					tipoCliente = TipoCliente.P.name();
				}
				medias = new HashMap<String, Fotografia>();
				if (this.cliente.getTemplate() != null) {
					if (this.cliente.getTemplate().getLogo() != null)
						medias.put("logo", new Fotografia(this.cliente.getTemplate().getLogo(),null,true));
					if (this.cliente.getTemplate().getCorretor() != null)
						medias.put("corretor", new Fotografia(this.cliente.getTemplate().getCorretor(),null,false));
					if (this.cliente.getTemplate().getBanner() != null)
						medias.put("banner", new Fotografia(this.cliente.getTemplate().getBanner(), null, false));
				} else {
					this.cliente.setTemplate(new Template());
				}
				// carrega listas para combos
				this.municipios = municipioDao.listMunicipiosPorUFOrdemNome(this.cliente.getEndereco().getMunicipio().getEstado());
				this.estados = estadoDao.listEstadosOrdemSigla();
				// carrega estado default
				this.estado = this.cliente.getEndereco().getMunicipio().getEstado();
				this.proprietarios = clienteDao.listClientesProprietarios();
			} catch (Exception e) {
				log.error(e.getMessage());
				this.municipios = new ArrayList<Municipio>();
			}		 			
			return "/faces/manager/xhtml/cliente/update.xhtml";
		} else {
			ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.edit.error")));
			return "/faces/manager/xhtml/cliente/list.xhtml";
		}
	}
	
	public String create() {
		this.cliente = new Cliente();
		tipoPessoa = TipoPessoa.FISICA.value();
		pessoaFisica = new PessoaFisica();
		pessoaJuridica = new PessoaJuridica();
		medias = new HashMap<String, Fotografia>();
		tipoCliente = TipoCliente.P.name();
		// Endereço //
		Estado estado;
		try {
			estado = estadoDao.findPorSigla(UF_DEFAULT);
			// carrega listas para combos
			this.municipios = municipioDao.listMunicipiosPorUFOrdemNome(estado);
			this.estados = estadoDao.listEstadosOrdemSigla();
			this.proprietarios = clienteDao.listClientesProprietarios();
			// carrega estado default
			this.estado = estado;
		} catch (Exception e) {
			log.error(e.getMessage());
			this.municipios = new ArrayList<Municipio>();
		}		 
		return "/faces/manager/xhtml/cliente/create.xhtml";
	}
	
	public void clienteDetalhado() {
		if (this.getCliente().getId() != null) {
			if (this.cliente.getPessoa() instanceof PessoaFisica) {
				pessoaFisica = (PessoaFisica) this.cliente.getPessoa();
			} else if ( this.cliente.getPessoa() instanceof PessoaJuridica ) {
				pessoaJuridica = (PessoaJuridica) this.cliente.getPessoa();
			}			
		} else {
			ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.select.error")));		
		}
	}
	
	public void reloadMunicipios() {
		try {
			this.municipios = municipioDao.listMunicipiosPorUFOrdemNome(estado);
		} catch (Exception e) {
			log.error(e.getMessage());
			this.municipios = new ArrayList<Municipio>();
		}				
	}
	
	public void onSelectedRow() {
		this.selectedCliente =  true; 
	}
	
	public void onPaged() {
		this.selectedCliente = false;
	}

	public LazyDataModel<Cliente> getLazyModelCliente() {
		return lazyModelCliente;
	}

	public void setLazyModelCliente(LazyDataModel<Cliente> lazyModelCliente) {
		this.lazyModelCliente = lazyModelCliente;
	}

	public Cliente getCliente() {
		if (this.cliente == null)
			this.cliente = new Cliente();
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}
	
	public Cliente getProprietario() {
		if (this.proprietario == null)
			this.proprietario = new Cliente();
		return proprietario;
	}

	public void setProprietario(Cliente proprietario) {
		this.proprietario = proprietario;
	}

	public final List getTiposPessoa() {
		List typeOptions = new ArrayList();
		for (TipoPessoa tp : TipoPessoa.values()) {
			typeOptions.add(new SelectItem(tp.value(), tp.toString()));
		}
		return typeOptions;
	}
	
	public final List<SelectItem> getTipoClientes() {
		List<SelectItem> items = new ArrayList<SelectItem>();
		for ( TipoCliente tipo: TipoCliente.values() ) {
			items.add(new SelectItem(tipo.name(), tipo.value()));
		}
		return items;
	}
	
	
	public String getTipoPessoa() {
		return tipoPessoa;
	}
	public void setTipoPessoa(String tipoPessoa) {
		this.tipoPessoa = tipoPessoa;
	}

	public List<Municipio> getMunicipios() {
		return municipios;
	}

	public void setMunicipios(List<Municipio> municipios) {
		this.municipios = municipios;
	}

	public Estado getEstado() {
		return estado;
	}

	public void setEstado(Estado estado) {
		this.estado = estado;
	}

	public List<Estado> getEstados() {
		return estados;
	}

	public void setEstados(List<Estado> estados) {
		this.estados = estados;
	}

	public List<Cliente> getProprietarios() {
		return proprietarios;
	}

	public void setProprietarios(List<Cliente> proprietarios) {
		this.proprietarios = proprietarios;
	}

	public PessoaFisica getPessoaFisica() {
		return pessoaFisica;
	}

	public void setPessoaFisica(PessoaFisica pessoaFisica) {
		this.pessoaFisica = pessoaFisica;
	}

	public PessoaJuridica getPessoaJuridica() {
		return pessoaJuridica;
	}

	public void setPessoJuridica(PessoaJuridica pessoaJuridica) {
		this.pessoaJuridica = pessoaJuridica;
	}

	public Integer getPageSize() {
		return this.pageSize;
	}

	public String getTipoCliente() {
		return tipoCliente;
	}

	public void setTipoCliente(String tipoCliente) {
		this.tipoCliente = tipoCliente;
	}

	public boolean isSelectedCliente() {
		return selectedCliente;
	}

	public void handleFileUpload(FileUploadEvent event) {
		
		ResourceBundle resource = ResourceBundle.getBundle("messages.MessageResources");
		String fileRealName = event.getFile().getFileName();
		String fileName = (StringUtils.randomName()+fileRealName.substring(fileRealName.indexOf("."),fileRealName.length())).toLowerCase();
		File file = new File(resource.getString("path.files.base.tmp")+fileName);
		/* Verifica tipo do arquivo para salvar no template */
		
		Long fileSize = event.getFile().getSize();							
		try {
			String fileType = file.toURI().toURL().openConnection().getContentType();
			/* Imagem = logo | Animacao = banner */
			if (fileType.contains("image")) {				
				BufferedImage bufferImage = ImageIO.read(event.getFile().getInputstream());
				if (fileType.contains("jpeg") || fileType.contains("jpg")){
					ImageIO.write(bufferImage, "JPG", file);
				} else if (fileType.contains("png")) {
					ImageIO.write(bufferImage, "PNG", file);
				} else if (fileType.contains("gif")) {
					ImageIO.write(bufferImage, "GIF", file);
				}
								
				/* salva dados da logo */
				if (!medias.containsKey("logo")) {
					medias.put("logo", new Fotografia(fileName, fileSize, true));
				} else if (tipoCliente.equals(TipoCliente.R.name()) && !medias.containsKey("corretor")) {
					medias.put("corretor", new Fotografia(fileName, fileSize, false));
				} else {
					ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
					FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
							bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.upload.error")));
				}
			} else {
				FileUtils.saveFile(event.getFile().getInputstream(), resource.getString("path.files.base.tmp"), fileName);
				
				/* salva dados do banner */
				if (!medias.containsKey("banner")) {
					medias.put("banner", new Fotografia(fileName, fileSize, false));
				} else {
					ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
					FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
							bundle.getString("messages.sumary.error"), bundle.getString("manager.cliente.upload.banner.error")));
				}
			}
		} catch (FileNotFoundException e) {
			log.error(e.getMessage(),e);
		} catch (IOException e) {
			log.error(e.getMessage(),e);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}	
	}
	
	private void persistMediaFiles() {
		
		if (!medias.isEmpty()) {
			ResourceBundle resource = ResourceBundle.getBundle("messages.MessageResources");
			ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
			HashMap<String, Fotografia> aux = (HashMap<String, Fotografia>) medias.clone();
			for (Fotografia mediaFile: medias.values()) {
				if (mediaFile.getAtivo()) {
					File tmpFile = new File(resource.getString("path.files.base.tmp")+mediaFile.getNome() );
					File prodFile = new File(resource.getString("path.files.images.base")+mediaFile.getNome() );
					if (tmpFile.exists()) {
						/** Movendo arquivo de media para diretório de produção **/
						tmpFile.renameTo(prodFile);				
					}
				} else if (!mediaFile.getAtivo()) {
					
					/** Remove arquivo de media do diretório temporário **/
					File tmpFile = new File(resource.getString("path.files.base.tmp")+mediaFile.getNome() );
					if (tmpFile.exists())
						tmpFile.delete();
					/** Remove arquivo de media do diretório de produção **/
					File prodFile = new File(resource.getString("path.files.images.base")+mediaFile.getNome() );
					if (prodFile.exists())
						prodFile.delete();
					
					aux.remove(mediaFile.getNome());
				}
			}		
			medias = aux;
		}				
	}
	
	public void removeMediaFile() {
		FacesContext context = FacesContext.getCurrentInstance();
		String mediaType = (String) context.getExternalContext().getRequestParameterMap().get("mediaType");
		
		Fotografia removedPhoto = medias.get(mediaType);
		removedPhoto.setAtivo(false);
		medias.remove(mediaType);
		medias.put(removedPhoto.getNome(), removedPhoto);
	}
	
	public List<Fotografia> getMediasAtivo() {
		
		List<Fotografia> mediaFiles = new ArrayList<Fotografia>();
		if (!medias.isEmpty()) {
			for (Fotografia fotografia : medias.values()) {
				if (fotografia.getAtivo()) {
					mediaFiles.add(fotografia);
				}
			}
		}		
		return mediaFiles;				
	}
	
	public final List<SelectItem> getPlanosAssinatura() {
		List<SelectItem> items = new ArrayList<SelectItem>();
		for ( Plano plano: Plano.values() ) {
			items.add(new SelectItem(plano.value(),plano.name()+" - "+plano.value()));
		}
		return items;
	}
	
}
